2. Praktyka CSS i RWD

Wyzwania:

  • nauczysz się obsługiwać Inspektora - podstawowe narzędzie frontend developera,
  • poznasz zaawansowane selektory oraz pseudoklasy CSS,
  • nauczysz się tworzyć strony mobilne.

Po poprzednim potrafisz już stworzyć prostą stronę – to znakomity początek! W tym tygodniu poznasz kilka nieco bardziej zaawansowanych zagadnień z zakresu HTML i CSS, ale zanim do nich przejdziemy, przyjrzyjmy się niezbędnemu narzędziu każdego developera – Inspektorowi.

2.1. Inspektor

Czy wiesz, że z poziomu swojej przeglądarki jesteś w stanie podejrzeć kod każdej strony internetowej? A nawet więcej – możesz "w locie" zmodyfikować tymczasowo (do momentu odświeżenia strony) kod i style każdej witryny i zobaczyć efekt na ekranie. W jaki sposób? Używając jednego z podstawowych narzędzi developera, czyli Inspektora.

Umiejętność obsługi Inspektora jest przydatna zwłaszcza wtedy, kiedy strona, nad którą pracujemy, nie działa, jak należy. Poprzez zbadanie kodu w Inspektorze jesteśmy w stanie łatwiej wychwycić błąd, np. sprawdzić, czy nasze style nie nadpisują się nawzajem.

Aby otworzyć Inspektora, kliknij prawym przyciskiem myszy na dowolnym elemencie strony internetowej i z menu kontekstowego wybierz "Zbadaj element".

image

Wszystkie popularne przeglądarki posiadają wbudowane narzędzia developerskie:

Chrome

image

Firefox

image

Microsoft Edge

image

Uwaga: w trakcie kursu będziemy omawiać narzędzia developerskie oferowane przez przeglądarkę Chrome, ponieważ naszym zdaniem są najbardziej funkcjonalne i intuicyjne w użyciu.

Klikając ikonkę z trzema kropkami, możesz między innymi wybrać, z której strony okna przeglądarki widoczny będzie Inspektor.

image

Możesz badać poszczególne elementy HTML na stronie, klikając je w lewej części okna Inspektora. Wtedy w prawej części okna pojawią się przypisane do nich style.

Najeżdżając na dany styl i odznaczając checkbox obok niego, możesz zakomentować (wyłączyć) daną właściwość i sprawdzić, co się stanie. Warto zapamiętać, że przekreślona właściwość (jak na obrazku poniżej) oznacza, że dany styl jest nadpisywany przez inną regułę i nie został zastosowany dla tego elementu:

image

Możesz również dodawać nowe style, pamiętaj jednak, że znikną one, gdy odświeżysz stronę:

image

Zachęcamy do eksperymentowania z Inspektorem i badania interesujących elementów stron, które odwiedzasz – to również dobra metoda, aby poszerzyć swoją wiedzę i nauczyć się nowych sztuczek!

2.2. Zaawansowane właściwości CSS

W poprzednim module poznaliśmy podstawy HTML i CSS, jednak był to jedynie wierzchołek góry lodowej. Sam CSS posiada dużo więcej zaawansowanych funkcji, z których część poznamy w niniejszym module. Lwia część pracy frontend developera polega właśnie na tworzeniu odpowiednich stylów, tak aby zapewnić użytkownikom optymalne korzystanie ze strony internetowej. Z tego powodu poznamy CSS bliżej.

Elementy blokowe i liniowe

Podczas pracy nad projektami w module 1 mieliśmy okazję użyć jednego z generycznych tagów HTML, a mianowicie <div>. Jak już zapewne wiesz, tagi <div> domyślnie zajmują 100% dostępnej szerokości oraz ustawiają się jeden pod drugim.

Takie elementy nazywamy blokowymi.

Do elementów blokowych należą m.in. <div>, <p>, nagłówki od <h1> do <h6>,<ul>, <ol> , <li> oraz tagi HTML5 typu <header>, <section>, <article> czy <footer>.

Elementom blokowym możemy nadawać właściwości width, height oraz margin i padding.

Przeciwieństwem elementów blokowych są elementy liniowe, czyli takie, które nie powodują złamania linii – domyślnie ustawiają się one jeden obok drugiego. Przykładami takich elementów są <a> i <span> (kolejny generyczny tag, którego można używać do przeróżnych celów).

Elementom liniowym nie możemy nadawać wymiarów za pomocą właściwości width i height. Nie zadziała również w ich przypadku margin-top ani margin-bottom. Możemy natomiast użyć marginesów bocznych (margin-left i margin-right) oraz paddingu.

Powyższe zasady ilustruje ten CodePen:


Właściwość display

Za pomocą CSS możemy łatwo zmienić domyślny sposób wyświetlania każdego elementu CSS. Służy to tego właściwość display. Może ona przyjmować wiele wartości, ale cztery najczęściej używane to:

  • display: none; - ukrywa element,
  • display: block; - element zostanie wyświetlony jako element blokowy,
  • display: inline; - element zostanie wyświetlony jako element liniowy,
  • display: inline-block; – bardzo ciekawa właściwość, która łączy cechy elementów blokowych i liniowych. Elementom typu inline-block możemy nadawać wymiary za pomocą width i height oraz margin i padding, ale jednocześnie te elementy nie spowodują złamania linii.

Zwróć uwagę na kod poniżej oraz sposób, w jaki poszczególne elementy pojawiają się na stronie. Nadaliśmy tam poszczególnym divom różne właściwości display, zmieniając w ten sposób ich wymiary oraz rozmieszczenie na stronie (spróbuj pobawić się tym kodem, zmieniając wartości dla display):


W jaki sposób można w praktyce zastosować właściwość display? Przykładowo, możemy zmienić za jej pomocą wyświetlanie elementów listy <ul> z pionowego (block) na poziome (inline-block):


Możemy też ostylować linowy element <a> w taki sposób, by wyglądał jak blokowy przycisk:


Możliwości jest mnóstwo i należy pamiętać o właściwości display, aby nie tworzyć nadmiarowych zagnieżdżeń w HTML (np. nie owijać liniowego elementu w blokowy tylko po to, by wyświetlić go w nowej linii).

Złożone selektory CSS

Poznaliśmy do tej pory selektory dla tagów, klas oraz identyfikatorów, a także napisaliśmy kilka bardziej złożonych selektorów. W tym submodule usystematyzujemy naszą wiedzę na ten temat.

Zagnieżdżone selektory

Aby wybrać w CSS elementy danego typu, ale tylko te, które znajdują się wewnątrz innego, określonego elementu, możemy skorzystać z zagnieżdżania selektorów. Wygląda to następująco:

header a {
    /* Styles for the links inside header */
}

Dzięki temu możemy określić wygląd tylko tych linków, które znajdują się wewnątrz elementu header. Możemy też korzystać z większej liczby selektorów:

header .main-navigation a {
    /* Styles for the links inside .main-navigation inside header */
}

Należy jednak przy tym pamiętać, że zagnieżdżanie selektorów ma swoją cenę w postaci prędkości ładowania strony. Dobrą praktyką jest niezagnieżdżanie zbyt dużej ilości selektorów.

Podobnie działa selektor wybierający element będący bezpośrednim potomkiem, który tworzymy za pomocą znaku >.

.example > div {
    /* Properties of divs that are directly inside .example */
}

W przykładzie powyżej, z użyciem znaku >, wybierzemy tylko te elementy div, które są bezpośrednim potomkiem (bezpośrednio zagnieżdżone) elementu HTML o klasie example. Elementy położone o dalsze poziomy niżej w drzewie dokumentu HTML nie będą objęte działaniem tego stylu.

Zagnieżdżone selektory w SCSS

Składnia SCSS, której używamy w niniejszym kursie, daje nam możliwość wygodniejszego zapisu zagnieżdżonych selektorów. Pisząc w SCSS, możemy użyć następującej składni:

header {
    a {
        /* Styles for the links inside header */
    }
}

Ten kod skompiluje się do CSS i zostanie odczytany przez przeglądarkę jako header a.

Oczywiście możemy używać większej liczby zagnieżdżeń, np.:

header {
    a {
        span {
            /* Styles for spans in the links inside header */
        }
    }
}

Należy jednak unikać przeciążania kodu SCSS zbyt głębokimi zagnieżdżeniami, gdyż style staną się wtedy zbyt nieczytelne i kłopotliwe w utrzymaniu.

Zagnieżdżając selektory w powyższy sposób, musimy pilnować wcięć w kodzie. Każdy kolejny poziom zagnieżdżenia składa się z jednego tabulatora lub dwóch znaków spacji.

Grupowanie selektorów

Kolejnym przydatnym skrótem przy pracy z CSS jest grupowanie selektorów. Możemy z niego skorzystać, gdy chcemy ten sam kod CSS przypisać wielu klasom lub elementom. Zamiast wpisywać go każdorazowo do wielu elementów, możemy zebrać powtarzające się właściwości i przypisać je do grupy selektorów. Robimy to, wymieniając je po prostu po przecinku:

h1, h2, h3 {
    text-align: center;
    font-weight: bold;
}

W ten sposób przypisaliśmy za pomocą jednej reguły ten sam styl do trzech typów nagłówków.

Pseudoklasy

Pseudoklasy pozwalają nam na wpływanie na wygląd elementów dokumentu, gdy znajdzie się on w pewnym stanie. Przez zmianę stylów CSS określonych za pomocą selektora pseudoklasy możemy sprawić, że jej wygląd będzie się zmieniał pod wpływem interakcji z użytkownikiem. Jednym z najczęstszych zastosowań pseudoklas jest zmiana wyglądu odnośników (linków), gdy użytkownik najedzie na niego myszką. Efekt taki możemy osiągnąć za pomocą pseudoklasy :hover. W przypadku pseudoklas korzystamy tylko z jednego dwukropka, jak w przykładzie poniżej:

a:hover {
    color: red;
}

Taki zapis sprawi, że element <a>, po najechaniu na niego kursorem, zmieni kolor na czerwony.

Inną popularną pseudoklasą typową dla odnośników jest :visited, dzięki której możemy określić wygląd odnośnika, który został już odwiedzony.

a:visited {
    color: green;
}

Wybrany (kliknięty, ale jeszcze nieodwiedzony) link może wyglądać jeszcze inaczej dzięki pseudoklasie :active.

a:active {
    color: #0000FF;
}

Pseudoklasa :hover dostępna jest również dla innych elementów niż odnośnik. Przykład poniżej zmienia tło dla pozycji na liście wewnątrz nagłówka po najechaniu na niego myszką.

header li:hover {
    background-color: #52B3D9;
}

Pamiętaj: a:hover musi występować po a:link i a:visited w kolejności definiowania stylów w CSS. Podobnie a:active piszemy po a:hover!

N-ty potomek

Innym interesującym rodzajem pseudoklas są te umożliwiające nam wybranie elementów będących n-tym w kolejności potomkiem swojego elementu-rodzica. Możemy w ten sposób np. zdefiniować unikalny wygląd dla pierwszego paragrafu danej sekcji lub wybrać tylko interesującą nas pozycję na liście. Możemy do tego wykorzystać następujące pseudoklasy:

p:first-child {
    /* First paragraph of the parent div */
}
li:last-child {
    /* Last item in an ul or ol list */
}
p:nth-child(3) {
    /* A paragraph which is the n-th child of the parent - in this example it's the third */
}

p:first-of-type {
  /* The first element of this type (a paragraph) of the parent div */
}

p:last-of-type {
  /* The last element of this type (a paragraph) of the parent div */
}

Pseudoklasy i n-ty potomek w SCSS

Tutaj również mamy opcję zastosowania wygodniejszej składni SCSS w następującej postaci:

a {
    &:active {
        color: #0000FF;
    }
}
li {
    &:last-child {
        /* Last item in an ul or ol list */
    }
}

Jak widzisz, do nadania styli na pseudoklasy n-tego potomka używamy w SCSS znaku &.

Zerknij na poniższy przykład, aby utrwalić sobie zagnieżdżanie w SCSS:


Jak widać, taki kod jest dużo bardziej przejrzysty. Ponadto jest on zgodny z zasadą DRY (Don't repeat yourself).

Wystarczy już teorii o (S)CSS. Możesz do niej stale wracać lub posiłkować się innymi źródłami. Przechodzimy do projektu! Od tej pory próbuj pisać zagnieżdżony SCSS, starając się nie przekraczać trzech poziomów zagnieżdżenia.

2.3. Zaczynamy projekt

Twoim zadaniem w tym module będzie zakodowanie strony agencji kreatywnej. Wiele elementów obecnych w projekcie omawialiśmy już w Module 1, dlatego nie będziemy podawać do nich szczegółowych instrukcji. Szerzej omówimy sobie natomiast nowe zagadnienia: wielopoziomowe menu, animowane przyciski oraz nowoczesny sposób tworzenia układu strony, czyli flexboksa.

Tak jak w poprzedniej części kursu, możesz zakodować stronę w 100% zgodnie z designem, lub dobrać własne treści, czcionki, kolory i zdjęcia.

Do stworzenia "wypełniaczy" treści, czyli popularnego lorem ipsum, możesz użyć generatora.

Na swojej stronie możesz użyć tych samych ilustracji co w projekcie lub znaleźć inne fotografie na stronie Pexels.

Spójrz na projekt:

image

Zwróć uwagę na to, z ilu sekcji się składa, oraz jakie wspólne komponenty w nich występują (np. te same rodzaje przycisków, nagłówków, układów tekstu). Jak pamiętasz, zgodnie z zasadą DRY (Don't Repeat Yourself), elementy powtarzające się stylujemy tylko raz.

Zachęcamy do rozrysowania sobie projektu (nawet na papierze) i zaznaczenia elementów, które się powtarzają lub są podobne i dla których należy przewidzieć wspólne style.

Załączamy również ściągawkę z podanymi wymiarami elementów, aby łatwiej było Ci samodzielnie kodować.

Tworzymy projekt i style bazowe

1. Zjedź do zadania w submodule 8 ("Wyślij projekt do Mentora") i naciśnij w nim guzik, aby przejść do edytora. Tak jak w poprzednim module, miej otwarty jednocześnie edytor i treść kursu, by łatwo można było przełączać się między jednym a drugim.

2. Tak samo, jak w Module 1, stwórz sobie w projekcie plik style.scss.

3. W pliku HTML dodaj strukturę bazową (zerknij do poprzedniego modułu, jeżeli jej nie pamiętasz), podepnij Font Awesome i czcionki z Google Fonts. W projekcie użyliśmy czcionek Signika (grubość 700) i Inconsolata (grubość 400), ale jeżeli chcesz, wybierz inne.

4. Ze strony Flat UI Colors wybierz z dowolnej palety trzy kolory, które wykorzystasz na stronie. W projekcie użyliśmy niebieskiego (#0097e6), zielonego (#33d9b2) i czerwonego (#ff5252). Dla tekstu będziemy używać kolorów #ffffff (biały – dla tekstu na barwnym tle) i #2c2c54 (granatowy – dla tekstu na jasnym tle). Możesz wykorzystać te same kolory lub wybrać inne, ale zwróć uwagę na odpowiedni kontrast, by tekst był czytelny.

5. W pliku .scss utwórz na samej górze sekcję /* Variables */ i dodaj w niej zmienne dla czcionek i kolorów. Sugerujemy nadać zmiennym kolorów nazwy color-one, color-two, color-three itp. zamiast np. color-red. W ten sposób Twój kod będzie bardziej uniwersalny.

6. W pliku .scss stwórz sekcję/* Global */` dla ogólnych stylów. Dodaj do niej znaną Ci już deklarację:

*, *::before, *::after {
        box-sizing: border-box;
}

7. Usuń także margines z <body> i zdefiniuj wielkość czcionki na 16px, a interlinię na 1.7. Ustaw także font-family odpowiadające czcionce wybranej dla tekstu (w projekcie jest to czcionka Inconsolata) oraz podstawowy kolor czcionki (w projekcie jest to #2c2c54).

8. .container w naszym projekcie będzie miał maksymalną szerokość 1140px i boczne paddingi o szerokości 20px. Będzie też wycentrowany w poziomie. Jeżeli potrzebujesz, wróć do poprzedniego modułu po odpowiednie deklaracje stylów.

9. Stwórz również selektor dla wszystkich elementów typu <section> i nadaj im dolny i górny padding o wartości 96px.

Podstawowe style gotowe! Możemy przejść zatem do zakodowania pierwszego elementu strony.

2.4. Komponent: wielopoziomowe menu

Na wielu stronach w internecie na pewno zdarzyło Ci się spotkać z nawigacją w postaci wielopoziomowego menu. Zaraz nauczysz się je tworzyć samodzielnie! Tego typu zadanie często pojawia się na rozmowach rekrutacyjnych na stanowiska frontendowe, więc tym bardziej warto przyłożyć się do tego zadania.

Menu w naszym projekcie wygląda tak:

image

Poziome menu pierwszego poziomu

Na początku zbudujmy strukturę HTML menu pierwszego poziomu.

1. Wewnątrz taga <body> stwórz element <nav> z klasą .navigation, a wewnątrz niego umieść <div> z klasą .container. Element <nav> to kolejny semantyczny tag, wprowadzony w HTML5 – służy on do zasygnalizowania, że dana lista linków na stronie to nawigacja.

2. W tym divie dodaj nieuporządkowaną listę wraz z kilkoma pozycjami (<li>). Każdy znacznik <li> powinien zawierać znacznik <a> (który na razie nigdzie nie będzie prowadził, więc powinien mieć atrybut href równy #). Wprowadź przykładowe teksty do tych elementów listy (takie jak na projekcie lub własne). Listy nieuporządkowane są często wykorzystywane właśnie do tworzenia elementów nawigacyjnych.

Efekt będzie podobny do poniższego:

image

Jak widzisz, nasza nieuporządkowana lista ma kilka domyślnych stylów, które musimy zlikwidować. W kolejnym kroku zatem poprawimy nieco wygląd naszej nawigacji.

3. W pliku .scss utwórz sekcję dla stylów nawigacji (/* Navigation */).

4. Całej nawigacji nadaj tło – wykorzystaj jeden z wybranych przez siebie kolorów. Dodaj jej dolny i górny padding równy 12px.

5. Usuniemy teraz domyślne style listy wypunktowanej. Dla selektora <ul> wewnątrz elementu .navigation musisz wyzerować padding i margin oraz wyłączyć punktory za pomocą właściwości list-style-type: none;. Więcej o tej właściwości i o tym, jakie wartości może przyjmować, przeczytasz na CSS Reference.

6. Teraz chcemy, aby elementy <li> w nawigacji były wyświetlane poziomo. Domyślnie te elementy są blokowe. Czy wiesz, jak sprawić, by stały się elementami typu inline-block? Tak jest: dla elementów listy <li>, znajdujących się wewnątrz elementu .navigation, musimy dodać deklarację display z odpowiednią wartością. Jeżeli nie pamiętasz, jaka to wartość, wróć do rozdziału "Właściwość display".

7. Tym samym elementom <li> dodaj przy okazji prawy margines równy 36px oraz pozycję relative. Będzie nam ona potrzebna już niedługo.

8. Ostylujmy teraz same linki w naszym menu. Dodaj selektor wybierający elementy <a> wewnątrz .navigation. Nadaj im właściwość text-decoration: none;, który zlikwiduje domyślny kolor podkreślenia, oraz ustaw kolor czcionki.

9. Całość wygląda już przyjemnie, jednak nasza nawigacja aż się prosi o to, żeby dodać jakiś efekt na :hover dla naszych linków. Może to być zmiana koloru czcionki (w projekcie na zielony - #33d9b2) lub cokolwiek innego, co podpowie Ci fantazja.

image

Rozwijane menu drugiego poziomu

Teraz możemy dodać menu drugiego poziomu. Będzie się wyświetlać dopiero po najechaniu na link pierwszego rzędu. Zacznijmy od HTML.

1. Wewnątrz pierwszego elementu <li>, zaraz za elementem <a>, dodaj element <ul> wraz z kilkoma pozycjami oraz linkami, tak jak poprzednio. Element ten powinien znaleźć się na tym samym poziomie zagnieżdżenia, co <a>.

2. Ustawmy elementy naszego menu drugiego poziomu w pionowym rzędzie. W tym celu dodaj selektor .navigation ul ul li i spraw, by był wyświetlany blokowo. Dodaj mu też dolny margines równy 12px.

3. Aby ukryć menu niższego poziomu (na razie będzie schowane), stwórz regułę display: none; dla list znajdujących się wewnątrz innych list w panelu nawigacji. Skorzystaj w tym celu ze znanych nam zagnieżdżonych selektorów.

Wyświetlamy listę drugiego poziomu

Przeanalizujmy strukturę naszego menu. Link drugiego poziomu jest elementem listy pierwszego poziomu. Aby wybrać listy drugiego rzędu, stworzylibyśmy następujący selektor:.navigation li ul { }.

W ten sposób wybieramy listy <ul> będące wewnątrz elementów listy pierwszego poziomu — tj. znajdujące się wewnątrz taga <li>. Chcemy wyświetlić te listy dopiero w momencie, gdy użytkownik najedzie kursorem na element <li>, zatem nasz selektor powinien wyglądać następująco: .navigation li:hover ul {...}. Do wyświetlenia listy wystarczy wewnątrz takiego selektora dodać właściwość display: block;.

1. Stwórz selektor wybierający listy drugiego rzędu po najechaniu myszką na element listy pierwszego rzędu, tak jak w opisie powyżej.

2. Dodaj właściwość display: block; wewnątrz utworzonego wyżej selektora i wycentruj w nim tekst. Menu w tym momencie zachowuje się dość dziwnie, ale zaraz to naprawimy.

3. Żeby lista drugiego poziomu nie rozpychała nam nawigacji, musimy ją "wyciągnąć z obiegu". Uzyskamy to dzięki dodaniu (tej zagnieżdżonej liście) position: absolute;. Dzięki temu, że elementy <li> w liście pierwszego poziomu są wypozycjonowane relatywnie (relative), elementy listy poziomu drugiego wypozycjonują się względem nich.

4. Nadajmy liście drugiego poziomu tło – w projekcie użyliśmy koloru białego.

5. Stwórz selektor wybierający linki (<a>) na liście drugiego poziomu i nadaj im kolor czcionki (w projekcie jest to niebieski - #0097e6) oraz efekt hover (w projekcie jest to kolor zielony - #33d9b2).

6. Prawie dobrze! Dopracujmy kilka ostatnich detali. Przede wszystkim chcielibyśmy, żeby linki drugiego poziomu zajmowały 100% szerokości swojego rodzica. Zapewni nam to właściwość display: block;. Uwaga! Upewnij się, że wyświetlanie blokowe będą miały tylko linki nawigacji drugiego poziomu! W przypadku linków nawigacji pierwszego poziomu nadal chcemy, żeby były liniowo-blokowe. Dodaj również linkom nawigacji drugiego poziomu padding równy 0 24px;.

7. Aby wycentrować rozwijane menu względem jego rodzica (to znaczy względem linka pierwszego poziomu), dodaj do listy drugiego rzędu właściwości left: 50%; oraz transform: translateX(-50%);. Jak pamiętasz, lista drugiego poziomu jest absolute, a jej rodzic jest relative. Użycie powyższej transformacji wycentruje element absoute w osi X, czyli poziomo. Na końcu dodaj liście drugiego poziomu górny padding równy 12px;.

Voila! Menu pojawiać się będzie po najechaniu kursorem na link pierwszego rzędu.

2.5. Podstawy flexboksa

Sugestia

Przed rozpoczęciem tego modułu (lub po teorii) warto przejść kurs Flexbox, aby przećwiczyć w praktyce podstawowe zagadnienia.

Nawigacja jest na miejscu, pora na kolejne części naszej strony! Do pozycjonowania elementów będziemy w nich wykorzystywać nowoczesną technikę tworzenia layoutów – flexbox. Do tej pory używaliśmy do tego właściwości float, ale flexbox jest znacznie bardziej wszechstronny. Zachęcamy do zaprzyjaźnienia się z nim – to kolejna technika, o którą często pojawia się pytanie na rozmowach rekrutacyjnych!

W tym module omówimy sobie tylko podstawowe założenia flexboksa. Znacznie więcej informacji znajdziesz w źródłach, do których linki zamieścimy na końcu.

Czym jest flexbox i kiedy z niego korzystać?

Flexbox powstał, aby sprostać wyzwaniom związanym z prawidłowym wyświetlaniem elementów na różnych urządzeniach. Jest on odpowiedzią na wiele bolączek związanych z tworzeniem layoutu.

Podstawową ideą przyświecającą temu sposobowi tworzenia layoutu jest umożliwienie kontenerowi zmiany wymiarów oraz rozmieszczenia elementów potomnych. Dzięki temu elementy znajdujące się w tym kontenerze zostaną rozciągnięte, by odpowiednio wypełnić dostępne miejsce, bądź zmniejszone, aby nie przekraczać granic kontenera. Takie rozwiązanie pozwala na zapewnienie prawidłowego wyświetlania strony na szerokiej gamie ekranów i przeglądarek.

Do czego możemy go wykorzystać? Przy jego użyciu możemy stworzyć inteligentny kontener, który w prosty sposób wyrówna treść. Dzięki flexboksowi takie zadania, jak np. wyśrodkowanie elementów w pionie stają się dużo prostsze, tak jak w przykładzie poniżej:


Możemy również dostosowywać wielkość elementów, aby np. dwa z nich miały określony wymiar, a pozostałe będą zajmować pozostałą szerokość. Jest to oczywiście wykonalne bez użycia fleksa, lecz wielu developerów jest zdania, że stosowanie tego rozwiązania jest dużo prostsze niż budowa layoutu w klasyczny sposób.

Wypróbujmy więc flexboksa od razu w praktyce i stwórzmy za jego pomocą sekcję Splash w naszym projekcie.

Sekcja Splash

Jaki Splash jest, każdy widzi – tytuł, podtytuł, przycisk, a całość wycentrowana w pionie i w poziomie na kolorowym tle.

image

1. W pliku HTML, pod nawigacją, stwórz element <header> o klasie splash. W CSS nadaj kolor tła (najlepiej taki, jak tło nawigacji), kolor czcionki, minimalną wysokość (w projekcie jest to 500px) oraz, co najważniejsze, display: flex;. To będzie nasz element-rodzic.

2. Wewnątrz <header> dodaj <div> o klasie splash-inner. W środku umieść element <h1> z klasą page-title i dowolną treścią, oraz <h2> z klasą page-subtitle - również wpisz w nim dowolną treść. Pod nagłówkiem <h2> umieść link (<a>) z atrybutem href równym # oraz dwiema klasami: btn oraz btn-one. W projekcie jego treść to "see our work", ale możesz wstawić własną.

3. W pliku styli nadaj elementowi splash-inner właściwość margin: auto;. I tylko tyle wystarczy, by dzięki flexboksowi perfekcyjnie wycentrować element w obu osiach! W projekcie dodatkowo nadaliśmy temu elementowi max-width: 70%;.

4. Następnie ostyluj oba nagłówki zgodnie z własnym uznaniem. W projekcie główny tytuł ma zerowy margines, czcionkę 72px, word-spacing równy -24px, wagę 700 i interlinię - 1.2. Podtytuł natomiast ma margines 24px 0;, wagę czcionki 400 i rozmiar 16px;.

Jak widzisz, w projekcie słowo "creatively" jest zapisane inną czcionką, niż reszta tytułu. Jak osiągnąć taki efekt? Przy pomocy znanego Ci już znacznika <span>! Owiń wybrane słowo w tytule w znacznik <span></span> i za pomocą selektora .page-title span nadaj mu wybrane style.

2.6. Komponent: animowany przycisk

Oba nagłówki w sekcji Splash są gotowe, ale czegoś jeszcze brakuje. Musimy ostylować przycisk! Nie róbmy tego jednak w pośpiechu – przyjrzyjmy się na spokojnie projektowi i sprawdźmy, jak sprytnie możemy ostylować wiele elementów za jednym zamachem. Umiejętność pisania oszczędnego, minimalistycznego kodu i inteligentne wykorzystanie klas pomocniczych to wyróżniki dobrego developera – warto więc uczyć się myśleć komponentowo!

Jak widzisz, w projekcie mamy kilka rodzajów przycisków:

image

Możesz w tym momencie zapytać: czy ten ostatni element na obrazku powyżej również jest przyciskiem, skoro wygląda jak link? Jak najbardziej – większość przycisków, które stworzymy, to właśnie linki (<a>), ostylowane w odpowiedni sposób. Nasze przyciski i linki to różne warianty tego samego elementu. Każdy z nich będzie miał dwie klasy – jedną ogólną, zawierającą style współdzielone z innymi elementami, oraz jedną szczegółową, odpowiedzialną za indywidualne cechy danego przycisku.

Nasza klasa ogólna to btn. Stwórz dla niej selektor w sekcji globalnych stylów Twojego pliku .scss i nadaj mu:

  • display: inline-block;
  • minimalną szerokość (min-width) równą 160px
  • margin: 24px auto 0 auto;
  • padding: 16px;
  • border-radius: 5px;
  • font-family takie jak reszta tekstu na Twojej stronie
  • font-size - w projekcie jest to 16px
  • text-align: center;
  • text-decoration: none;
  • cursor: pointer;

Ponadto chcemy, aby domyślny przycisk miał dwupikselową ciągłą ramkę. Dodajmy zatem:

  • border-width: 2px;
  • border-style: solid;

Prawie dobrze! Jak widzisz w podglądzie, powstał "generyczny", granatowy przycisk. Tak będzie wyglądał każdy button, któremu nadasz tylko klasę ogólną btn. Aby nadać przyciskowi indywidualny charakter, ostylujmy jego klasę szczegółową.

Pod selektorem .btn dodaj selektor .btn-one i nadaj mu dowolny border-color i color (w projekcie mają one kolor biały).

Udało się!

Animujemy przycisk

Nasz button wygląda całkiem nieźle, ale dodajmy mu nieco życia poprzez wprowadzenie animacji po najechaniu na przycisk kursorem myszy:

image

Posłużymy się do tego celu gradientem.

Czym jest gradient?

Gradienty w CSS pozwalają na stworzenie płynnych przejść pomiędzy kolorami tła. Posiadają one wiele różnorodnych właściwości pozwalających osiągać złożone efekty, jednak w tym ćwiczeniu skorzystamy ze stosunkowo prostych rozwiązań.

Do zdefiniowania gradientu jak powyżej wystarczy nam następująca deklaracja:

background: linear-gradient(red, blue);

W praktyce potrzebne jest też zastosowanie vendor prefixów, by gradient taki wyświetlił się prawidłowo we wszystkich przeglądarkach, więc nasz kod będzie wyglądał najczęściej następująco:

.grad {
    background: red; /* for browsers that do not support gradients */
    background: -webkit-linear-gradient(red, yellow); /* Safari 5.1 - 6.0 */
    background: -o-linear-gradient(red, yellow); /* Opera 11.1 - 12.0 */
    background: -moz-linear-gradient(red, yellow); /* Firefox 3.6 do 15 */
    background: linear-gradient(red, yellow); /* standard syntax */
}

Na potrzeby tego ćwiczenia będziemy korzystać ze standardowej składni, pomijając prefiksy.

Aby kontrolować kąt, pod jakim przebiega gradient, możemy też podać jego obrót w stopniach, tak jak poniżej:

background: linear-gradient(-45deg, green, yellow);

Możemy też ustalać przezroczyste kolory:

background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);

Aby stworzyć płynne przejście pomiędzy jednym stanem a drugim (np. w przypadku użycia pseudoklasy :hover), skorzystamy z właściwości transition, którą pamiętasz z porzedniego modułu: transition: all 1s; (możesz oczywiście zmienić czas animacji według własnego uznania).

W pliku .scss zdefiniuj wartość transition jako zmienną (np. $transition: all 1s;) i nadawaj ją elementom w ten sposób: transition: $transition;.

Teraz pokolorujemy nasz przycisk i ustawimy tło jako gradient.

W swoim pliku stylów:

1. Do selektora .btn-one dodaj background-image: linear-gradient(90deg, #ffffff 50%, transparent 50%);, zastępując w razie potrzeby wartość #ffffff (biały kolor) swoją własną zmienną lub wybranym kodem koloru.

Teraz schowamy nasz gradient, a następnie dodamy kod, który sprawi, że po najechaniu kursorem na przycisk gradient wypełni go w całości.

2. Do selektora .btn dodaj właściwość background-position: 100% 0; oraz background-size: 300%;.

3. Stwórz selektor dla stanu :hover elementu .btn i nadaj mu background-position: 0 100%; oraz biały kolor czcionki.

4. W razie potrzeby zmień również kolor czcionki dla stanu :hover elementu .btn-one, aby była widoczna na wybranym tle.

Aby uruchomić animację, dodaj selektorowi .btn właściwość transition podaną wyżej.

Gotowe!

2.7. Ćwiczymy flexboksa

Sekcja "Our services"

Wypróbuj teraz swoją umiejętność myślenia komponentowego, samodzielnie tworząc kolejną sekcję w projekcie ("Our services"). Znasz wszystkie niezbędne do tego właściwości, więc powinna wystarczyć Ci tylko garść wskazówek:

1. Zacznij od HTML tej sekcji: najpierw tag section, w nim .container, tytuł, potem div, który będzie wrapperem (rodzicem) dla trzech ułożonych poziomo "pudełek z treścią", a w nim trzy elementy potomne, czyli właśnie nasze "pudełka".

2. "Pudełka" ułożysz poziomo, nadając na ich diva-rodzica właściwości display: flex;, flex-wrap: wrap; oraz justify-content: space-between;, a na samo "pudełko" - flex: 0 0 33.333%;. Pamiętaj, że "pudełka" muszą być bezpośrednimi potomkami diva-rodzica, nie może być między nimi żadnych innych wrapperów.

3. Półprzezroczyste liczby w tle każdego "pudełka" wypozycjonujesz, nadając im pozycję absolute, a ich bezpośredniemu rodzicowi pozycję relative. Wtedy możesz manipulować offsetem (czyli wartościami właściwości left, right, top, bottom) liczb.

4. W każdym "pudełku", pod jego tytułem, umieść dwa akapity z tekstem, a pierwszemu z nich pogrub czcionkę, używając pseudoklasy :first-of-type.

5. Buttony w "pudełkach" mają zachowywać się tak, jak przycisk w sekcji Splash. Nadaj każdemu z nich klasę ogólną btn oraz klasy szczegółowe (btn-two, btn-three, btn-four) i ostyluj je analogicznie do klasy btn-one, zmieniając kolory. Uwaga: w projekcie buttony są na tej samej wysokości, bo w każdym "pudełku" tekst ma tę samą długość. Gdy do któregoś z nich dodasz więcej tekstu, button przesunie się w dół. W ramach zadania dodatkowego (po wykonaniu reszty projektu) zastanów się, w jaki sposób można sprawić, by przyciski zawsze były na tej samej wysokości, niezależnie od ilości tekstu.

6. Pamiętaj o nazywaniu klas zgodnie z dobrymi praktykami, o których mówiliśmy w poprzednim module.

7. Zwracaj uwagę na to, które elementy powtarzają się w designie (np. tytuły) i wydzielaj ich style do klas ogólnych, których będziesz używać wielokrotnie.

Aby ułatwić sobie pracę, możesz skorzystać ze ściągawki ze zwymiarowanymi elementami:

image

Sekcja "Our work"

Podobnie jak poprzednia sekcja, ta część projektu nie powinna sprawić Ci większych problemów. Kilka wskazówek poniżej:

1. Struktura sekcji jest taka sama, jak poprzednio: section, .container, tytuł, wrapper dla "pudełek", a w nim cztery elementy potomne.

2. Wrapper pudełek będzie potrzebować właściwości display: flex;, flex-wrap: wrap; oraz justify-content: space-between;. Czy pamiętasz, że już tworzyliśmy dokładnie taki element? Wykorzystaj istniejące style i klasy, aby nie duplikować niepotrzebnie kodu.

3. Aby wyświetlić dwa "pudełka" w rzędzie, nadaj im właściwość flex: 0 0 50%;.

4. Każde "pudełko" składa się z obrazka i tekstu obok. Czy pamiętasz, że w Module 1 tworzyliśmy bardzo podobny element? Śmiało możesz wrócić do tamtego zadania i skopiować potrzebne style i strukturę. Pamiętaj o właściwości object-fit: cover;! Tym razem zadanie jest łatwiejsze o tyle, że wszystkie obrazki znajdują się po lewej stronie swojego "pudełka".

5. Półprzezroczysta kolorowa warstwa nałożona na obrazek (a właściwie na jego bezpośredniego diva-rodzica) to nic innego, jak pseudoelement :after z opacity: 0.3, przesunięty o 20px w prawo i w dół. Uwaga: aby warstwa mogła wychodzić poza obręb obrazka (jak na projekcie), divowi-rodzicowi nie nadawaj overflow: hidden;.

6. W opisie każdego "pudełka" wstaw dwa akapity z treścią. Drugiemu z nich pogrub czcionkę, używając pseudoklasy :last-of-type.

7. Link "read more" to również przycisk. Przy najechaniu kursorem nie chcemy jednak gradientowego tła, a tylko prostą zmianę koloru czcionki. Nadaj temu elementowi klasę ogólną btn i szczegółową btn-five. W CSS selektorowi btn-five usuń ramkę (border: none;) oraz nadaj margin: 36px 0;, padding: 0;, text-align: left;.

Ściągawka z wymiarami:

image

Dla chętnych: spraw, by po najechaniu na obrazek półprzezroczysta warstwa zachowywała się tak, jak na tym gifie: link.

Sekcja "Contact"

Tę sekcję również stworzysz samodzielnie – formularze nie powinny mieć już przed Tobą tajemnic! Przy układaniu layoutu skorzystamy tutaj znowu z flexboksa. Będzie Ci jak zwykle potrzebny wrapper-rodzic, a w nim dwa elementy potomne: formularz (<form>) i <div> z danymi kontaktowymi. Aby formularz zawsze zajmował zawsze dwa razy większą szerokość niż <div>, nadaj formularzowi flex: 2 0 0;, a divowi z danymi - flex: 1 0 0;. W projekcie formularz ma prawy padding o wartości podanej na poniższej ściągawce.

Przycisk formularza również powinien mieć gradientową animację tła.

image

Stopka

Na pewno wiesz już, w jaki sposób tworzyć okrągłe ikony z kolorowym tłem. Wykorzystaj tę umiejętność, aby zakodować stopkę (<footer>) projektu – linki do mediów społecznościowych:

image

Jeżeli chodzi o HTML, będzie Ci potrzebna nieuporządkowana lista (<ul>), w której zawrzesz znaczniki <li>, a w nich <a> oraz <i> z odpowiednią klasą skopiowaną ze strony Font Awesome. Przykładowy pojedynczy znacznik <li> powinien wyglądać następująco:

<li><a href="#"><i class="fab fa-facebook-f"></i>Facebook</a></li>

Po napisaniu HTML, Twój efekt powinien być podobny do poniższego:

image

Teraz Twoim zadaniem będzie jedynie ostylować ikony według projektu. Proste? :) Pamiętaj, żeby tagach <li> pozostawić zapisane słownie nazwy serwisów społecznościowych – jest to dobra praktyka ułatwiająca interpretowanie strony np. czytnikom dla niewidomych. Słowa te możesz ukryć w stylach, nadając na znacznik <li> w tej liście font-size: 0;. Docelową wielkość czcionki, która zdeterminuje rozmiar ikony, nadaj na znacznik <i> wewnątrz tej listy.

Dla chętnych

Spraw, aby po najechaniu kursorem myszy na kolorowe kółko powiększało się ono (wraz z ikoną w środku) do 1.2 swojej oryginalnej wielkości (animacja ma być płynna). W tym celu poczytaj o transformacji scale.

Zwymiarowany projekt:

image

2.8. Tworzymy responsywny layout!

Czy wiesz, że statystyki wskazują, że w niektórych krajach (np. w USA) przekroczono już punkt, w którym więcej użytkowników przegląda strony na urządzeniach mobilnych niż na komputerach? Z tego powodu jedną z podstawowych umiejętności frontend developera jest dostosowywanie budowanych stron do mniejszych ekranów.

Istnieją różne możliwości tworzenia mobilnych wersji stron. Niektóre firmy decydują się na udostępnienie osobnego adresu (zwykle zaczynającego się od m lub mobile), gdzie przekierowywani są użytkownicy odwiedzający stronę na smartfonie. Tworzenie wielu wersji jednej strony (to podejście nazywamy AWD, czyli Adaptive Web Design) sprawia jednak, że trzeba napisać znacznie więcej kodu. Także wszelkie zmiany wyglądu, np. na stronie głównej, wymagają modyfikacji nie w jednym, ale w kilku szablonach.

Zupełnie odmiennym podejściem w zakresie dostosowywania witryny pod wiele urządzeń jest RWD, czyli Responsive Web Design. Opiera się ono na tworzeniu jednego szablonu pod wszystkie urządzenia wraz z dodatkowymi regułami w CSS, które mówią o tym, jak ma wyglądać strona na poszczególnych rozdzielczościach. Np. poniższa strona to jeden szablon HTML/CSS, który dostosowuje się do różnych urządzeń.

image

Dwie drogi w RWD

W tym kursie wykorzystamy RWD do tworzenia wersji mobilnych naszych projektów. W zakresie tworzenia stron responsywnych wyróżnia się dwa podejścia.

image

Graceful degradation

Czyli przypadek, w którym zaczynamy od wersji strony dla ekranów o dużej rozdzielczości (desktop) i dopiero potem dostosowujemy ją do ekranów mniejszych.

Progressive enhancement

Znane także jako mobile first. Polega na stworzeniu najpierw wersji dostosowanej do rozdzielczości właściwych urządzeniom mobilnym, a następnie rozbudowywanie jej i przystosowanie do większych ekranów

Które podejście wybrać?

Nie jest jednak tak, że jedno podejście jest w naturalny sposób lepsze czy gorsze. W praktyce ciągle trwa wśród frontendowców gorąca debata o wyższości jednego sposobu nad drugim. My – po początkowym zachwycie nad mobile first – skłaniamy się bardziej ku temu, aby zaczynać od desktopów, ale ze świadomością, że potem czeka nas mobile.

Viewport

Przy okazji RWD, należy wspomnieć o viewport. Jest to ta część strony, która jest widoczna w danym momencie na ekranie użytkownika. Im mniejsze urządzenie, tym mniejsza widoczna przestrzeń.

Aby strona była responsywna, warto najpierw określić odpowiedni rozmiar viewport. Ma to głównie na celu to, aby strona wgrana na urządzenie mobilne nie była wyjściowo powiększona (zoom), ale dostosowana do wielkości urządzenia (100% szerokości ekranu tego urządzenia).

Najczęściej używa się rzadko modyfikowanego meta-tagu w HTML (w sekcji head) mającego postać:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Pierwsza część (content="width=device-width) ustawia szerokość strony tak, aby odpowiadała szerokości urządzenia. Druga (initial-scale=1.0) ustawia początkowy poziom powiększenia (zoom) na urządzeniach mobilnych.

Dodaj teraz powyższy tag <meta name="viewport" content="width=device-width, initial-scale=1.0"> do sekcji <head> w swoim projekcie.

Media queries

W tym module stworzymy podstawową kompatybilność z urządzeniami mobilnymi za pomocą tak zwanych media queries.

Media queries to instrukcje warunkowe w CSS, które mówią przeglądarce np.: Jeżeli ekran jest węższy niż 768px, rozciągnij dany element na 100% szerokości okna.

Podstawowe media query budujemy następująco:

image

Z czego składa się media query?

  • wyrażenie @media – - zawsze rozpoczyna deklarację media query.
  • warunki, które muszą zostać spełnione, by reguły zawarte w media query zostały zastosowane. W powyższym przykładzie style będą działać w przedziale od 768px do 991px szerokości ekranu.
  • podobnie jak w CSS, tworzymy parę nawiasów klamrowych ({ }).
  • wewnątrz nawiasów tworzymy selektory CSS, których style chcemy zmodyfikować dla danych szerokości ekranu. W powyższym przykładzie zdecydowaliśmy, że wielkość czcionki elementu section-title na ekranach w zdefiniowanym zakresie (czyli 768-991px) ma wynosić 24px. Selektory wewnątrz media queries umieszczamy tak, jak zwykle w CSS - jeden pod drugim.

W media queries można używać jednego lub więcej warunków (np. tylko min-width, tylko max-width lub obu).

Dostosowujemy stronę do mobile

Wszystkie style, które dotychczas napisaliśmy, tworzone były z myślą o dużych ekranach. Dostosujemy teraz stronę do mniejszych rozdzielczości: telefonów i tabletów. Przyjmiemy, że style dla telefonów będą obejmować ekrany do 767px szerokości, a dla tabletów – od 768px do 991px.

Zacznijmy od stylów dla telefonów. W edytorze kliknij link Publikacja > Udostępnij, skopiuj adres swojej strony i wklej go tutaj: http://responsiv.eu/, by obejrzeć swoje dzieło na różnych urządzeniach.

Również manipulując szerokością okna podglądu w edytorze lub szerokością okna przeglądarki (mając otwartą w niej pełną wersję swojej strony) możesz zasymulować wyświetlanie strony na różnych rozdzielczościach.

Jak widzisz, flexbox robi całkiem dobrą robotę, jeżeli chodzi o wygląd projektu na małych ekranach, niemniej jednak jest kilka rzeczy, które musimy skorygować.

1. W pliku .scss, na samym dole, stwórz nową sekcję /* Media */. Tam będziemy trzymać wszystkie style mobilne.

2. Dodaj następujące media query:

@media (max-width: 767px) {

}

Teraz wewnątrz tego media query (między jego nawiasami klamrowymi) umieścimy style poprawiające wygląd naszej strony na najmniejszych wyświetlaczach.

Ułożenie elementów w kolumnach

Po pierwsze, chcielibyśmy, aby wszystkie elementy, które na dużych ekranach wyświetlają się w rzędzie – czyli "pudełka" w sekcjach "Our service", "Our work" oraz "Contact" – wyświetlały się na smartfonach w kolumnie, czyli jedno pod drugim. Jest to standardowy sposób rozmieszczania tego typu elementów na małych ekranach.

Jak to zrobić? Czy pamiętasz wrapper naszych "pudełek", któremu nadaliśmy właściwości display: flex;, flex-wrap: wrap; oraz justify-content: space-between;? Upewnij się, że stosujesz ten wrapper we wszystkich wymienionych wyżej sekcjach. Wewnątrz media query utwórz selektor dla tego wrappera i nadaj mu właściwość flex-direction: column;. I już. Oto potęga flexboksa!

Poprawiamy obrazki

Obecnie obrazki w sekcji "Our work" są dość duże, więc na małych ekranach treść sekcji nie mieści się w viewport. Ponadto obok obrazka jest tekst, który też musi być czytelny. Co by z tym zrobić? Powiedzmy, że na telefonach chcemy wyświetlać "pudełka" w tej sekcji w następujący sposób:

image

Posłuż się Inspektorem, aby odpowiedniemu elementowi w kodzie nadać max-width: 100%; oraz height: 150px;. Jeżeli ten element ma w Twoim kodzie pozycję absolute, zmień ją w media query na relative.

Jak widzisz, zgodnie z tym, co powiedzieliśmy sobie wyżej, do media queries dodajemy tylko te style, które chcemy zmodyfikować na danej szerokości ekranu.

Dodajemy odstępy

Przejdźmy do sekcji "Contact". Tutaj "pudełka" są już ułożone w kolumnie, ale efekt będzie lepszy, jeżeli "odkleją" się od siebie. Dodaj zatem w media query górny margines divowi z danymi kontaktowymi (Inspektor jest Twoim przyjacielem!).

Sprawdź też, czy poprawek marginesów nie wymagają "pudełka" w innych sekcjach.

Ostatnie poprawki

Przyjrzyj się jeszcze raz krytycznym okiem swojej stronie na mniejszych ekranach. Co jeszcze można poprawić? Może zmniejszyć odstępy między linkami w nawigacji, jeżeli nie mieszczą się w jednej linii? Może zmniejszyć padding selektora section, aby strona była bardziej kompaktowa? Może zmniejszyć czcionkę nagłówków, aby więcej treści mieściło się na ekranie? Korzystaj z Inspektora, aby wypróbowywać różne style i sprawdzać, które selektory musisz zmodyfikować w media queries.

Przykładowa wersja projektu na smartfonie: pobierz

Obejrzyj również swoją stronę na symulacji tabletów na stronie http://responsiv.eu/. Jeżeli uważasz, że wymaga ona poprawek, stwórz nowe media query:

@media (min-width: 768px) and (max-width: 991px) {

}

i wpisz w nim potrzebne style.

Zadanie: Wyślij projekt do sprawdzenia

Kiedy Twój projekt będzie gotowy do wysłania, kliknij Wyślij do sprawdzenia, aby przekazać go Mentorowi.

2.9. Podsumowanie

Ten moduł uporządkował i rozwinął Twoją wiedzę na temat zaawansowanych selektorów CSS oraz nowoczesnego sposobu tworzenia layoutów. Ponadto potrafisz już tworzyć proste strony responsywne oraz podstawowe animacje CSS.

Poniżej zamieszczamy linki do ciekawych materiałów, które przydadzą Ci się do samodzielnej nauki.

Flexbox

  • A Complete Guide to Flexbox – świetne, ilustrowane kompedium wiedzy o flexboksie z licznymi przykładami. Niezbędnik każdego developera!
  • Flexyboxes – wizualny generator layoutów flexboksowych.

Animacje

;